package com.panopset.sf.apps.blackjack;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.StringWriter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

import com.panopset.Util;
import com.panopset.centralen.resource.ImageResource;
import com.panopset.compat.Strings;
import com.panopset.game.Tile;
import com.panopset.game.blackjack.BlackjackCard;
import com.panopset.game.blackjack.BlackjackGame;
import com.panopset.game.blackjack.BlackjackTable;
import com.panopset.game.blackjack.ExecListener;
import com.panopset.game.blackjack.Hand;
import com.panopset.game.blackjack.LayoutChips;
import com.panopset.game.blackjack.LayoutDealer;
import com.panopset.game.blackjack.LayoutPlayer;
import com.panopset.game.blackjack.Player;
import com.panopset.game.blackjack.ScreenSizer;
import com.panopset.sf.OsgwResizable;
import com.panopset.sf.Windoc;
import com.panopset.sf.apps.SwingCardPainter;
import com.panopset.sf.apps.SwingChipPainter;
import com.panopset.tools.CommandBinder.Command;

public class Felt implements ExecListener {

    //private int cycle = 0;
    private ScreenSizer ss = ScreenSizer.SMALL;
    private final BlackjackGame m;
    final Windoc w;
    public static final String ARROW_IMAGE = "/com/panopset/game/card/arrow.png";
    private final static Image arrowImg = new ImageResource(ARROW_IMAGE)
            .getImage();

    public Felt(Windoc windoc, BlackjackGame game) {
        w = windoc;
        m = game;
    }

    private void updateTable() {
        if (width != getPanel().getWidth() || ss != m.getConfig().getScreenSizer()) {
            width = getPanel().getWidth();
            getTable().setBounds(f.getWidth(), f.getHeight());
            chpptr = new SwingChipPainter(m.getConfig());
            cptr = new SwingCardPainter(m.getConfig());
            font0 = new Font(Font.SERIF, Font.PLAIN,m.getConfig().getScreenSizer().getFontSize());
            font1 = new Font(Font.SERIF, Font.BOLD,
                    m.getConfig().getScreenSizer().getFontSize());
            ss = m.getConfig().getScreenSizer();
        }
        if (w.getFrame().isActive() && !getPanel().hasFocus()) {
            getPanel().grabFocus();
            getPanel().requestFocus();//or requestFocusInWindow
        }
    }

    public void paint(final Graphics2D g) {
        updateTable();
        if (Strings.isPopulated(m.mistakeMessage)) {
            g.setColor(Color.RED);
        } else {
            g.setColor(getFeltColor());
        }
        g.fillRect(0, 0, getTable().getTableTile().getWidth(), getTable()
                .getTableTile().getHeight());
        synchronized (m) {
            paintChips(g, getTable().getChipTray());
            if (getTable().getStatusTile() != null) {
                paintStatus(g, getTable().getStatusTile());
            }
            paintDealer(g, getTable().getDealerTile());
            paintPlayer(g, getTable().getPlayerTile());
            paintMsgLandscape(g, getTable().getMsgTile());
        }
        g.setColor(Color.CYAN);
        //g.drawString("Cycle: " + cycle++, 100, 100);
    }

    private SwingChipPainter chpptr;
    private SwingCardPainter cptr;

    private BlackjackTable bjt;

    private BlackjackTable getTable() {
        if (bjt == null) {
            bjt = new BlackjackTable();
        }
        return bjt;
    }

    private int width = -1;

    boolean dbg = false;

    private void paintStatus(Graphics2D g, Tile t) {
        if (dbg) {
            g.setColor(Color.BLUE);
            g.fillRect(t.getLeft(), t.getTop(), t.getWidth(), t.getHeight());
        }
        g.setColor(Color.WHITE);
        g.setFont(getFont0());
        int verticalSeparator = m.getConfig().getScreenSizer().getVerticalTextSeparator();
        int y = t.getTop() + verticalSeparator;
        for (String s : m.getGameStatusVertical()) {
            g.drawString("  " + s.trim(), t.getLeft(), y);
            y = y + verticalSeparator;
        }
    }

    private void paintChips(Graphics2D g, Tile t) {
        if (chpptr == null) {
            return;
        }
        if (dbg) {
            g.setColor(Color.CYAN);
            g.fillRect(t.getLeft(), t.getTop(), t.getWidth(), t.getHeight());
        }
        g.setColor(new Color(0x66, 0x33, 0x44));
        g.fillRoundRect(t.getLeft(), t.getTop(), t.getWidth(), t.getHeight(),
                20, 20);
        g.setColor(Color.BLACK);
        LayoutChips lc = new LayoutChips(t.getLeft(), t.getBottom(),
                chpptr.getChipWidth(), chpptr.getChipHeight());
        chpptr.paintChips(g, lc.chipXnextBet, lc.chipY, m.getNextBet());
        chpptr.paintChips(g, lc.chipXstack, lc.chipY, m.getBankroll()
                .getChipsInTray() - m.getNextBet());
        g.setColor(Color.WHITE);
        g.setFont(getFont0());
        int verticalSeparator = m.getConfig().getScreenSizer().getVerticalTextSeparator();
        int y = t.getTop() + verticalSeparator;
        for (String s : m.getStatusChipsVertical()) {
            g.drawString("  " + s.trim(), t.getLeft(), y);
            y = y + verticalSeparator;
        }
        if (getTable().getStatusTile() == null) {
            for (String s : m.getGameStatusVertical()) {
                g.drawString("  " + s.trim(), t.getLeft(), y);
                y = y + verticalSeparator;
            }
        }
    }

    private void paintDealer(Graphics2D g, Tile t) {
        if (dbg) {
            g.setColor(Color.RED);
            g.fillRect(t.getLeft(), t.getTop(), t.getWidth(), t.getBottom());
        }
        LayoutDealer o = new LayoutDealer(t, new int[] {cptr.getCardWidth(),
                cptr.getCardHeight() }, m.getCycle());
        g.setColor(Color.BLACK);
        for (BlackjackCard bc : o.cy.getDealer().getCardsCopy()) {
            cptr.paintCard(g, bc.getCard(), o.getNextDealerX(), 0);
        }
    }

    private void paintPlayer(Graphics2D g, Tile t) {
        if (dbg) {
            g.setColor(Color.YELLOW);
            g.fillRect(t.getLeft(), t.getTop(), t.getWidth(), t.getBottom());
        }
        g.setColor(Color.BLACK);
        LayoutPlayer o = new LayoutPlayer(t, new int[] {cptr.getCardWidth(),
                cptr.getCardHeight() }, m.getCycle(), new int[] {
                chpptr.getChipWidth(), chpptr.getChipHeight() });
        int cardX = o.getPlayerCardXstart();
        boolean arrowHasBeenDrawn = false;
        for (Player p : m.getCycle().getPlayers()) {
            Hand activeHand = p.getActiveHand();
            for (Hand h : p.getAllHands()) {
                int handFirstCardX = cardX;
                for (BlackjackCard bc : h.getCardsCopy()) {
                    cptr.paintCard(g, bc.getCard(), cardX, o.getPlayerY()
                            - o.cardH);
                    cardX = cardX + o.cardSpacer;
                }
                cardX = cardX + o.cardW;
                StringWriter sm = new StringWriter();
                sm.append(h.getMessage());
                Color fg00 = Color.BLACK;
                Color fg01 = Color.WHITE;

                if (h.isDoubleDowned()) {

                    int initialBetValue = h.getChips() / 2;

                    chpptr.paintChips(g, handFirstCardX, o.getPlayerChipY(),
                            initialBetValue);

                    chpptr.paintChips(g, handFirstCardX + chpptr.getChipWidth()
                            + chpptr.getChipHeight(), o.getPlayerChipY(),
                            initialBetValue);

                } else {
                    chpptr.paintChips(g, handFirstCardX, o.getPlayerChipY(),
                            h.getChips());
                }

                if (activeHand != null && h == activeHand) {
                    fg00 = new Color(0xff, 0xff, 0x00);
                    fg01 = new Color(0xdd, 0x00, 0x00);
                    if (!arrowHasBeenDrawn) {
                        g.drawImage(arrowImg, handFirstCardX + o.chipW,
                                o.getPlayerChipY(), null);
                        arrowHasBeenDrawn = true;
                    }
                }

                g.setFont(getFont1());
                g.setColor(fg00);
                g.drawString(sm.toString(), handFirstCardX, o.getPlayerMsgY());
                g.setColor(fg01);
                g.drawString(sm.toString(), handFirstCardX + 1,
                        o.getPlayerMsgY() + 1);
            }
        }
    }

    private Font font0;

    private Font getFont0() {
        if (font0 == null) {
            font0 = new Font(Font.SERIF, Font.PLAIN,
                    m.getConfig().getScreenSizer().getFontSize());
        }
        return font0;
    }

    private Font font1;
    private Font getFont1() {
        if (font1 == null) {
            font1 = new Font(Font.SERIF, Font.PLAIN,
                    m.getConfig().getScreenSizer().getFontSize());
        }
        return font1;
    }
    private void initGforMsg(Graphics2D g, Tile t) {
        if (dbg) {
            g.setColor(Color.GRAY);
            g.fillRect(t.getLeft(), t.getTop(), t.getWidth(), t.getBottom());
        }
        g.setColor(Color.BLACK);
        g.setFont(getFont0());
        if (Strings.isPopulated(m.mistakeMessage)) {
            g.setColor(new Color(0xff, 0x00, 0x00));
        } else {
            g.setColor(getLightMsgColor());
        }
        g.setFont(getFont0());
    }

    private void paintMistakeMessage(Graphics2D g, Tile t, int y, int vs) {
        if (Strings.isPopulated(m.mistakeMessage)) {
            g.setColor(new Color(0xff, 0x00, 0x00));
        } else {
            g.setColor(new Color(0x00, 0x88, 0x00));
        }
        if (Strings.isPopulated(m.mistakeMessage)) {
            g.setColor(Color.YELLOW);
            g.drawString(m.mistakeMessage, 0, y);
        } else if (Strings.isPopulated(m.simpleMessage)) {
            g.setColor(Color.WHITE);
            g.drawString(m.simpleMessage, 0, y);
        }
        y = y - vs;
        // Swing only:
        g.setFont(getFont0());
        g.setColor(new Color(0xff, 0xff, 0x99));
        g.drawString(commander.toString(), t.getLeft(), y);
    }

    private void paintMsgLandscape(Graphics2D g, Tile t) {
        initGforMsg(g, t);
        int verticalSeparator = m.getConfig().getScreenSizer().getVerticalTextSeparator();
        int y = t.getBottom() - (verticalSeparator / 4);
        paintMistakeMessage(g, t, y, verticalSeparator);
    }

    public final BlackjackCmdBinder commander = new BlackjackCmdBinder();
    JComponent p;

    private OsgwResizable osgr;

    private JPanel f;

    public JComponent getPanel() {
        if (p == null) {
            p = w.cf.createPanel(new BorderLayout());
            osgr = new OsgwResizable(60) {
                @Override
                public void paintCycle(final Graphics2D g) {
                    paint(g);
                }
            };
            f = osgr.getPanel();
            p.add(BorderLayout.CENTER, f);
            p.add(BorderLayout.SOUTH, getControlPanel());
            p.setName(Util.x("Game"));
        }
        return p;
    }

    private JPanel cp;

    private JPanel getControlPanel() {
        if (cp == null) {
            cp = new JPanel(new GridLayout(2, 1));

            JPanel r1 = w.cf.createPanel(new FlowLayout());
            JPanel r2 = w.cf.createPanel(new FlowLayout());

            int i = 0;

            for (final Command c : commander.cmds) {
                JButton btn = new JButton(c.up);
                w.cf.registerPassiveComponent(btn);
                btn.setMnemonic(c.dk);
                btn.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        m.exec(c.a);
                    }

                });
                if (i > 5) {
                    r2.add(btn);
                } else {
                    r1.add(btn);
                }
                i = i + 1;
            }
            cp.add(r1);
            cp.add(r2);
        }
        return cp;
    }

    @Override
    public void update() {
        if (osgr == null) {
            return;
        }
        if (!m.isAutomatic()) {
            osgr.getOsgw().update();
        }
    }

    private Color feltColor;

    private Color getFeltColor() {
        if (feltColor == null) {
            feltColor = new Color(0x00, 0x88, 0x00);
        }
        return feltColor;
    }

    private Color lightMsgColor;

    private Color getLightMsgColor() {
        if (lightMsgColor == null) {
            lightMsgColor = new Color(0x33, 0x66, 0x33);
        }
        return lightMsgColor;
    }
}
